/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.foxinline.utilitarios;

import br.com.foxinline.manager.pesquisar.ManagerPesquisarProtocolo;
import br.com.foxinline.modelo.Anexo;
import br.com.foxinline.modelo.Processo;
import br.com.foxinline.util.Msg;
import java.io.*;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import net.coobird.thumbnailator.name.Rename;
import org.apache.commons.io.FileUtils;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.UploadedFile;

/**
 *
 * @author laverson
 */
public class ArquivoUtilitario {

    private static final String REAL_PATH_TMP = "/tmp/uploads/";
    private static final String REAL_PATH_OPT = "/opt/uploads/";
    private static final String THUMBNAIL = "thumbnail";

    public ArquivoUtilitario() {
    }

    /**
     *
     * Adiciona um anexo a para upload basic
     *
     * @param event
     * @throws FileNotFoundException
     * @throws SQLException
     * @throws IOException
     */
    public Anexo adicionarArquivo(UploadedFile event) {
        try {
            Anexo anexo = new Anexo();

            String nomeReal = event.getFileName().replace("/", " ");

            anexo.setNome(nomeReal.replace("/", " ").trim());

            // Aqui cria o diretorio caso não exista
            File file = new File(REAL_PATH_TMP);
            file.mkdirs();

            byte[] arquivo = event.getContents();
            String caminho = REAL_PATH_TMP + nomeReal.trim();

            gravarArquivo(caminho, arquivo);
            criarMiniatura(caminho);

            anexo.setUrl(REAL_PATH_TMP);
            anexo.setArquivo(arquivo);
            anexo.setNomeExibicao(nomeReal);
            anexo.setTipo(event.getContentType());
            System.err.println(anexo.getId() + " - " + anexo);
            return anexo;
        } catch (Exception ex) {
            Msg.messagemError("Erro ao Copiar Arquivo para Anexo");
            return null;
        }
    }

    /**
     *
     * Adiciona um anexo a lista de anexos do processo que está sendo adicionado
     * a lista de processos do protocolo
     *
     * @param event
     * @throws FileNotFoundException
     * @throws SQLException
     * @throws IOException
     */
    public Anexo adicionarArquivo(FileUploadEvent event) throws FileNotFoundException, SQLException, IOException {
        try {
            Anexo anexo = new Anexo();

            String nomeReal = event.getFile().getFileName().replace("/", " ");

            anexo.setNome(nomeReal.replace("/", " ").trim());

            // Aqui cria o diretorio caso não exista
            File file = new File(REAL_PATH_TMP);
            file.mkdirs();

            byte[] arquivo = event.getFile().getContents();
            String caminho = REAL_PATH_TMP + nomeReal.trim();

            gravarArquivo(caminho, arquivo);
            criarMiniatura(caminho);

            anexo.setUrl(REAL_PATH_TMP);
            anexo.setArquivo(arquivo);
            anexo.setNomeExibicao(nomeReal);
            anexo.setTipo(event.getFile().getContentType());

            return anexo;
        } catch (Exception ex) {
            Msg.messagemError("Erro ao Copiar Arquivo para Anexo");
            return null;
        }
    }

    /**
     *
     * Grava os anexos no diretório "/opt/uploads/"
     *
     * @param anexos, lista de anexos a serem gravados
     */
    public void gravarAnexos(List<Anexo> anexos) {
        for (Anexo a : anexos) {
            if (a.getId() == null) {
                String oldPath = a.getUrl();
                try {
                    SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss");
                    String data = dateFormat.format(new Date());

                    a.setNomeExibicao(a.getNome());
                    a.setNome(data + a.getNome());
                    a.setUrl(REAL_PATH_OPT);

                    gravarArquivo(a.getUrl() + a.getNome(), a.getArquivo());
                    criarMiniatura(a.getUrl().concat(a.getNome()));
                } catch (FileNotFoundException ex) {
                    Logger.getLogger(ManagerPesquisarProtocolo.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IOException ex) {
                    Logger.getLogger(ManagerPesquisarProtocolo.class.getName()).log(Level.SEVERE, null, ex);
                }

                try {
                    excluirArquivo(new File(oldPath.concat(a.getNomeExibicao())));
                } catch (FileNotFoundException ex) {
                    Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }

    /**
     *
     * Grava o 'arquivo' no diretório informado pela 'url'
     *
     * @param caminho caminho onde o arquivo vai ser gravado
     * @param arquivo arquivo a ser gravado no 'caminho'
     * @throws FileNotFoundException
     * @throws IOException
     */
    private void gravarArquivo(String caminho, byte[] arquivo) throws FileNotFoundException, IOException {
        // esse trecho grava o arquivo no diretório
        FileOutputStream fos = new FileOutputStream(caminho);
        fos.write(arquivo);
        fos.close();
    }

    /**
     *
     * Grava os anexos dos processos
     *
     * @param processos, lista de processos contendo os anexos a serem gravados
     */
    public void gravarAnexosDoProcesso(List<Processo> processos) {
        for (Processo p : processos) {
            gravarAnexos(p.getAnexos());
        }
    }

    /**
     *
     * Exclui o arquivo do diretório
     *
     * @param f Arquivo a ser removido
     * @return true, se removido com sucesso, false caso contrário
     * @throws FileNotFoundException
     */
    public boolean excluirArquivo(File f) throws FileNotFoundException {
        try {
            String[] s = f.getPath().split("/");
            String nomeImagem = s[3];
            String caminhoImagemMiniatura = "/" + s[1] + "/" + s[2] + "/";
            caminhoImagemMiniatura += THUMBNAIL + "." + nomeImagem;

            //converte o objeto file em array de bytes
            List<InputStream> inputStreams = new ArrayList<InputStream>();
            inputStreams.add(new FileInputStream(f.getPath()));
            inputStreams.add(new FileInputStream(caminhoImagemMiniatura));

            File fThumb = new File(caminhoImagemMiniatura);

            for (InputStream inputStream : inputStreams) {
                byte[] bytes = new byte[(int) f.length()];
                int offset = 0;
                int numRead = 0;
                while (offset < bytes.length && (numRead = inputStream.read(bytes, offset, bytes.length - offset)) >= 0) {
                    offset += numRead;
                }
                inputStream.close();
            }

            fThumb.delete();
            f.delete(); //Deleta o arquivo onde foi criado
            return true;
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return false;
    }

    /**
     *
     * Cria uma miniatura da imagem existente no caminho informado
     *
     * @param caminhoImagem Caminho completo da imagem Ex: ../imagens/icon.png
     */
    public static void criarMiniatura(String caminhoImagem) {
        try {
            Thumbnails.of(new File(caminhoImagem)).crop(Positions.CENTER).size(60, 60).toFiles(Rename.PREFIX_DOT_THUMBNAIL);
        } catch (IOException ex) {
            try {
                FacesContext facesContext = FacesContext.getCurrentInstance();
                ServletContext servletContext = (ServletContext) facesContext.getExternalContext().getContext();

                File fileSource = new File(servletContext.getRealPath("/media/images/imageJPG.png"));
                String[] path = caminhoImagem.split("/");

                File fileTarget = new File("/" + path[1] + "/" + path[2] + "/" + THUMBNAIL + "." + path[3]);

                FileUtils.copyFile(fileSource, fileTarget);

                Thumbnails.of(fileTarget).crop(Positions.CENTER).size(60, 60).toFiles(Rename.PREFIX_DOT_THUMBNAIL);

            } catch (IOException ex1) {
                Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex1);
            }
        }
    }

    public List<Anexo> removerBytes(List<Anexo> anexos) {
        for (Anexo anexo : anexos) {
            anexo.setArquivo(null);
        }
        return anexos;
    }
}
